{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "# 正则化逻辑回归\n",
    "正则化是成本函数中的一个术语，它使算法更倾向于“更简单”的模型（在这种情况下，模型将更小的系数）。这个理论助于减少过拟合，提高模型的泛化能力。\n",
    "\n",
    "你是工厂主管，你有一些芯片在两次测试的结果，你需要决定它们是否合格，你手里有之前的结果，现在需要构建一个逻辑回归模型进行预测。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "      Test1    Test2  Accepted\n0  0.051267  0.69956         1\n1 -0.092742  0.68494         1\n2 -0.213710  0.69225         1\n3 -0.375000  0.50219         1\n4 -0.513250  0.46564         1",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>Test1</th>\n      <th>Test2</th>\n      <th>Accepted</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>0.051267</td>\n      <td>0.69956</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>-0.092742</td>\n      <td>0.68494</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>-0.213710</td>\n      <td>0.69225</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>-0.375000</td>\n      <td>0.50219</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>-0.513250</td>\n      <td>0.46564</td>\n      <td>1</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "path = 'ex2data2.txt'\n",
    "data = pd.read_csv(path, header=None, names=['Test1', 'Test2', 'Accepted'])\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "            Test1       Test2    Accepted\ncount  118.000000  118.000000  118.000000\nmean     0.054779    0.183102    0.491525\nstd      0.496654    0.519743    0.502060\nmin     -0.830070   -0.769740    0.000000\n25%     -0.372120   -0.254385    0.000000\n50%     -0.006336    0.213455    0.000000\n75%      0.478970    0.646563    1.000000\nmax      1.070900    1.108900    1.000000",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>Test1</th>\n      <th>Test2</th>\n      <th>Accepted</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>count</th>\n      <td>118.000000</td>\n      <td>118.000000</td>\n      <td>118.000000</td>\n    </tr>\n    <tr>\n      <th>mean</th>\n      <td>0.054779</td>\n      <td>0.183102</td>\n      <td>0.491525</td>\n    </tr>\n    <tr>\n      <th>std</th>\n      <td>0.496654</td>\n      <td>0.519743</td>\n      <td>0.502060</td>\n    </tr>\n    <tr>\n      <th>min</th>\n      <td>-0.830070</td>\n      <td>-0.769740</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th>25%</th>\n      <td>-0.372120</td>\n      <td>-0.254385</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th>50%</th>\n      <td>-0.006336</td>\n      <td>0.213455</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th>75%</th>\n      <td>0.478970</td>\n      <td>0.646563</td>\n      <td>1.000000</td>\n    </tr>\n    <tr>\n      <th>max</th>\n      <td>1.070900</td>\n      <td>1.108900</td>\n      <td>1.000000</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.describe()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## 绘制样本图像"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "<Figure size 1200x800 with 1 Axes>",
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA/0AAAKnCAYAAADUXS1FAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAACRAElEQVR4nOzde3hU1b3/8c9MwoQoTtDDJdBOBdQI1ih4oxBAWucI6qlIPG20NqhFLYJaQavS1lhjW2qr4PES8Cje8vMSpSLQC62hppJAxaIoKhIFLFFJrFIyApExyf79sc8MzGQymSRz23ver+eZJ2bvNcOa7IyZz6y1vsthGIYhAAAAAABgO85UdwAAAAAAACQGoR8AAAAAAJsi9AMAAAAAYFOEfgAAAAAAbIrQDwAAAACATRH6AQAAAACwKUI/AAAAAAA2RegHAAAAAMCmslPdATtob2/Xxx9/rCOOOEIOhyPV3QEAAAAA2JxhGPr88881dOhQOZ2dj+cT+uPg448/lsfjSXU3AAAAAAAZpqGhQV/96lc7PU/oj4MjjjhCkvnDdrvdKe4NAAAAAMDufD6fPB5PMI92htAfB4Ep/W63m9APAAAAAEiarpaYU8gPAAAAAACbIvQDAAAAAGBThH4AAAAAAGyKNf0AAAAAYEOGYai1tVVtbW2p7gp6ICsrS9nZ2b3eFp7QDwAAAAA24/f7tWvXLu3fvz/VXUEvHHbYYRoyZIhcLlePH4PQDwAAAAA20t7erh07digrK0tDhw6Vy+Xq9WgxksswDPn9fv3rX//Sjh07dNxxx8np7NnqfEI/AAAAANiI3+9Xe3u7PB6PDjvssFR3Bz2Um5urPn366J///Kf8fr/69u3bo8ehkB8AAAAA2FBPR4aRPuJxDfktAAAAAADApgj9AAAAAAAk2bBhw3TPPfck/N8h9AMAAAAA0sb69euVlZWl8847L9Vd6SBZQT2eCP0AAAAAgIhaWqSmJvNrsixdulTXXnutXn75ZX388cfJ+4dtitAPAAAAAAhRWysVF0v9+kn5+ebX4mKpri6x/+7evXtVVVWlq6++Wuedd54ee+yxkPOrVq3S6aefrr59+2rAgAGaPn168NyBAwd08803y+PxKCcnR8cee6yWLl0aPP/WW2/pnHPOUb9+/TR48GCVlpbq008/DZ6fPHmyrrnmGl1zzTXKy8vTgAEDdOutt8owjOD5f/7zn5o7d64cDkfINoi1tbWaOHGicnNz5fF4dN1112nfvn3B85988om+/e1vKzc3V8OHD9eTTz4Z7x9dpwj9AAAAAICgxYulSZOkVauk9nbzWHu7+f3EidKSJYn7t5999lmNHDlSxx9/vL7//e/rkUceCYbuP/zhD5o+fbrOPfdcvf7661qzZo3OOOOM4H1nzJihp59+Wvfee6+2bNmiBx98UP369ZMk7dmzR9/61rc0ZswY/eMf/9Dq1avV1NSk7373uyH//uOPP67s7Gxt2LBB//M//6OFCxfq4YcfliQ9//zz+upXv6ry8nLt2rVLu3btkiRt27ZNU6dO1YUXXqg333xTVVVVqq2t1TXXXBN83Msuu0wNDQ166aWXtGzZMlVUVOiTTz5J3A/yEA4j8BNEj/l8PuXl5am5uVlutzvV3QEAAACQwb744gvt2LFDw4cP7/be7rW1ZuCPlhIdDmntWqmoqJcdjaCoqEjf/e539aMf/Uitra0aMmSInnvuOU2ePFnjx4/XiBEj9P/+3//rcL/6+nodf/zxevHFF+X1ejuc/8UvfqG1a9fqz3/+c/DYhx9+KI/Ho61bt6qgoECTJ0/WJ598orfffjs4in/LLbdo5cqVeueddySZa/qvv/56XX/99cHHueKKK5SVlaUHH3wweKy2tlZnnnmm9u3bp507d+r444/Xhg0bdPrpp0uS3n33XY0aNUqLFi0Keaxw0a5lrDmUkX4AAAAAgCRp4UIpKyt6m6wsadGi+P/bW7du1YYNG3TxxRdLkrKzs1VSUhKcor9p0yadddZZEe+7adMmZWVl6cwzz4x4/o033tBLL72kfv36BW8jR46UZI7UB3zjG98ImbY/btw4vffee2pra+u032+88YYee+yxkMeeMmWK2tvbtWPHDm3ZskXZ2dk69dRTg/cZOXKk+vfvH9sPppeyk/KvAAAAAADSWkuLtGLFwSn9nWltlZYvN9vn5sbv31+6dKlaW1s1dOjQ4DHDMJSTk6P7779fuVH+sWjnJLNWwLe//W3deeedHc4NGTKk553+v8f+4Q9/qOuuu67Dua997Wuqr6/v1eP3FqEfAAAAACCfr+vAH9DebraPV+hvbW3VE088obvvvltnn312yLkLLrhATz/9tE466SStWbNGl19+eYf7FxYWqr29XX/7298iTu8/5ZRT9Lvf/U7Dhg1TdnbnMfiVV14J+f7vf/+7jjvuOGX93/QHl8vVYdT/lFNO0TvvvKNjjz024mOOHDlSra2t2rhxY3B6/9atW7Vnz55O+xFPTO8HAAAAAMjtlpwxJkSn02wfL7///e/173//WzNnztSJJ54Ycrvwwgu1dOlS3XbbbXr66ad12223acuWLdq8eXNw5H7YsGG69NJL9YMf/EAvvPCCduzYoZqaGj377LOSpDlz5mj37t26+OKL9eqrr2rbtm3685//rMsvvzwkxO/cuVPz5s3T1q1b9fTTT+u+++7Tj370o+D5YcOG6eWXX9ZHH30UrPx/8803a926dbrmmmu0adMmvffee1qxYkWwkN/xxx+vqVOn6oc//KFeeeUVbdy4UVdccUWXsxPihdAPAECA39+78wAAWFhurjRtmhRlIFySeX769PhP7fd6vcrLy+tw7sILL9Q//vEPHXXUUXruuee0cuVKjR49Wt/61re0YcOGYLvFixfrv//7vzV79myNHDlSV155ZXDbvKFDh6qurk5tbW06++yzVVhYqOuvv179+/eX85BPOmbMmKGWlhadccYZmjNnjn70ox/pqquuCp4vLy/XBx98oGOOOUYDBw6UJJ100kn629/+pvr6ek2cOFFjxoxRWVlZyDKFRx99VEOHDtWZZ56p4uJiXXXVVRo0aFD8foBRUL0/DqjeDwA2UFUllZVJ1dWSx9PxfEOD5PVK5eVSSUny+wcAQIysXL0/lSZPnqzRo0frnnvuSXVXgqjeDwBAPPj9ZuCvr5cmTzYD/qEaGszj9fVmO0b8AQA2NWGCVFFhBvvwEf/sbPN4RYX9Ar+dEfoBAHC5zBH+ESOk7dtDg38g8G/fbp6vrjbbAwBgU7NmmSP506YdXOPvdJrfr11rnod1UL0fAADJnNJfU3Mw4E+eLFVWSqWlBwN/TU3kqf8AANhMUZF5a2kxq/S73fFdw5+OampqUt2FhCD0AwAQEB78A3MXCfwAgAyVm2v/sG93TO8HAOBQHo85wn+oykoCP5KP3SQAAHFA6AcA4FANDeaU/kOVlnYs7gckUlWVVFjY+e9dQ4N5vqoquf0CAFgOoR8AgIDwon11dZGL+wGJxG4SAIA4IvQDACB1DPw1NdL48eZXgj+Sid0kAABxROgHAMDvl7zeyFX6A8X9AgHM62VkFYkX/ns3ebK0bl3HD6aoNQEA6AKhHwAAl0sqL5cKCiIHqUAAKygw2zGyimQID/5FRQR+AOjCBx98IIfDoU2bNqW6Kx2kqm+EfgAAJKmkRNq8ufMg5fGY50tKktsvZDZ2kwCQYS677DI5HA45HA716dNHw4cP10033aQvvvgipvt7PB7t2rVLJ554Ylz6k84fIsSK0A8AQEBXI/iM8CPZ2E0CQCqkeMvQqVOnateuXdq+fbsWLVqkBx98ULfddltM983KylJ+fr6ys7MT2kcrIfQDAACkI3aTAJAKabBlaE5OjvLz8+XxeHTBBRfI6/XqxRdflCS1t7drwYIFGj58uHJzc3XyySdr2bJlwftGGpl/6623dM4556hfv34aPHiwSktL9emnnwbPt7e36ze/+Y2OPfZY5eTk6Gtf+5p++ctfSpKGDx8uSRozZowcDocmT54cvN/DDz+sUaNGqW/fvho5cqQqKipCnseGDRs0ZswY9e3bV6eddppef/31eP+oYkLoBwAASDfsJgEgFdJwy9C33npL69atk+v/ZtstWLBATzzxhJYsWaK3335bc+fO1fe//3397W9/i3j/PXv26Fvf+pbGjBmjf/zjH1q9erWampr03e9+N9hm/vz5+vWvf61bb71V77zzjp566ikNHjxYkhncJam6ulq7du3S888/L0l68sknVVZWpl/+8pfasmWLfvWrX+nWW2/V448/Lknau3ev/uu//ksnnHCCNm7cqJ///Oe68cYbE/ZzioY5DwAAAOkklt0kAh8IeL1mrQmWngCIh8CWoYH/x0yefPD/QUncMvT3v/+9+vXrp9bWVh04cEBOp1P333+/Dhw4oF/96leqrq7WuHHjJEkjRoxQbW2tHnzwQZ155pkdHuv+++/XmDFj9Ktf/Sp47JFHHpHH41F9fb2GDBmi//mf/9H999+vSy+9VJJ0zDHHaMKECZKkgQMHSpL+4z/+Q/n5+cHHuO2223T33XeruLhYkjkj4J133tGDDz6oSy+9VE899ZTa29u1dOlS9e3bV1//+tf14Ycf6uqrr07IzywaQj8AAEA6CewmUVZmvqnubDcJr5fdJADEX/iHi5MnmwVES0uTtoPIN7/5TS1evFj79u3TokWLlJ2drQsvvFBvv/229u/fr//8z/8Mae/3+zVmzJiIj/XGG2/opZdeUr9+/Tqc27Ztm/bs2aMD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evvtt7V7927t3r1bb731lnw+n6677rpE9FGSNGDAAGVlZampqSnkeFNTk/K72Mz0rrvu0q9//Wv95S9/0UknnRS17YgRIzRgwAC9//77nbbJycmR2+0OuQEAAAAAkG66HfpXr16tiooKjRo1KnjshBNO0AMPPKA//elPce3coVwul0499VStWbMmeKy9vV1r1qzRuHHjOr3fb37zG91xxx1avXq1TjvttC7/nQ8//FCfffaZhgwZEpd+AwAAAACQKt0O/e3t7erTp0+H43369FF7e3tcOtWZefPm6aGHHtLjjz+uLVu26Oqrr9a+fft0+eWXS5JmzJgRUujvzjvv1K233qpHHnlEw4YNU2NjoxobG7V3715J0t69e/XjH/9Yf//73/XBBx9ozZo1mjZtmo499lhNmTIloc8FQGxaWqSmJvMrAAAAgO7pduj/1re+pR/96Ef6+OOPg8c++ugjzZ07t9M18PFSUlKiu+66S2VlZRo9erQ2bdqk1atXB4v77dy5U7t27Qq2X7x4sfx+v/77v/9bQ4YMCd7uuusuSVJWVpbefPNNnX/++SooKNDMmTN16qmnau3atcrJyUnocwEQXW2tVFws9esn5eebX4uLpbq6VPcMAAAAsA6HYRhGd+7Q0NCg888/X2+//XaweF1DQ4NOPPFErVy5Ul/96lcT0tF0Fuv+iEA6S6fKwIsXS3PmsDcxAAAA0JlYc2i3Q78kGYah6urq4FZ5o0aNCtkGL9MQ+mFltbXSwoXSihWhewDfcENq9gCurZUmTZKi/Z/J4ZDWrmWPYgAAAGSuhIZ+hCL0w6rScUS9uFhatSq0P+Gys80PJpYtS16/AAAAgHQSaw7t9pr+6667Tvfee2+H4/fff7+uv/767j4cgBSprTUDv2F0DNitrebx2bOTu4a+pcWccRAt8Evm+eXLKe4HAAAAdKXbof93v/udiiLMqR0/fryWMewGWMbCheYIfzRZWdKiRcnpj2TWFIh1E5D2drM9AAAAgM51O/R/9tlnysvL63Dc7Xbr008/jUunACRWuo6ou91mTYFYOJ1mewAAAACd63boP/bYY7V69eoOx//0pz9pxIgRcekUgMRK1xH13FxzrX52dvR22dnS9Omp32UAAAAASHddvLXuaN68ebrmmmv0r3/9S9/61rckSWvWrNHdd9+te+65J979A5AAgRH1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V2J6jI0bN2rTpk2aOXNmh3Nz5szRgAEDdMYZZ+iRRx6RYRhx63um6821e/LJJzVgwACdeOKJmj9/vvbv3x/yuIWFhRo8eHDw2JQpU+Tz+fT222/H/4lkoHi87iSpublZbrdb2dnZIcd53cWP3+/Xxo0b5fV6g8ecTqe8Xq/Wr18f8T7r168PaS+Zr6FA+x07dqixsTGkTV5ensaOHdvpY6L7enLtwu3fv19ffvmljjrqqJDjNTU1GjRokI4//nhdffXV+uyzz+La90zX02u3d+9eHX300fJ4PJo2bVrI3yxed8kRj9fd0qVLddFFF+nwww8POc7rLv109fcuHr8PmSa76yZA9zU2NmrQoEEhx7Kzs3XUUUepsbExpsdYunSpRo0apfHjx4ccLy8v17e+9S0ddthh+stf/qLZs2dr7969uu666+LW/0zW02v3ve99T0cffbSGDh2qN998UzfffLO2bt2q559/Pvi4hwZ+ScHvY/2dQHTxeN19+umnuuOOO3TVVVeFHOd1F1+ffvqp2traIr4m3n333Yj36ew1FLi2ga/R2qD3enLtwt18880aOnRoyBvWqVOnqri4WMOHD9e2bdv0k5/8ROecc47Wr1+vrKysuD6HTNWTa3f88cfrkUce0UknnaTm5mbdddddGj9+vN5++2199atf5XWXJL193W3YsEFvvfWWli5dGnKc11166uzvnc/nU0tLi/7973/3+v/DmYbQj2655ZZbdOedd0Zts2XLll7/Oy0tLXrqqad06623djh36LExY8Zo3759+u1vf0v46EKir92hIbGwsFBDhgzRWWedpW3btumYY47p8eMiea87n8+n8847TyeccIJ+/vOfh5zjdQfEx69//Ws988wzqqmpCSkId9FFFwX/u7CwUCeddJKOOeYY1dTU6KyzzkpFVyFp3LhxGjduXPD78ePHa9SoUXrwwQd1xx13pLBn6I6lS5eqsLBQZ5xxRshxXnfIFIR+dMsNN9ygyy67LGqbESNGKD8/X5988knI8dbWVu3evVv5+fld/jvLli3T/v37NWPGjC7bjh07VnfccYcOHDignJycLttnqmRdu4CxY8dKkt5//30dc8wxys/P71BVtampSZK69biZKBnX7vPPP9fUqVN1xBFHaPny5erTp0/U9rzuemfAgAHKysoKvgYCmpqaOr1W+fn5UdsHvjY1NWnIkCEhbUaPHh3H3me2nly7gLvuuku//vWvVV1drZNOOilq2xEjRmjAgAF6//33CR9x0ptrF9CnTx+NGTNG77//viRed8nSm2u3b98+PfPMMyovL+/y3+F1lx46+3vndruVm5urrKysXr+WMw1r+tEtAwcO1MiRI6PeXC6Xxo0bpz179mjjxo3B+/71r39Ve3t7MAxGs3TpUp1//vkaOHBgl203bdqkI488kuDRhWRdu4BNmzZJUvBN0Lhx47R58+aQUPriiy/K7XbrhBNOiM+TtKlEXzufz6ezzz5bLpdLK1eu7LAdVSS87nrH5XLp1FNP1Zo1a4LH2tvbtWbNmpBRxUONGzcupL1kvoYC7YcPH678/PyQNj6fT6+88kqnj4nu68m1k6Tf/OY3uuOOO7R69eqQuhud+fDDD/XZZ5+FBEn0Tk+v3aHa2tq0efPm4HXhdZccvbl2zz33nA4cOKDvf//7Xf47vO7SQ1d/7+LxWs44qa4kCPuaOnWqMWbMGOOVV14xamtrjeOOOy5k67APP/zQOP74441XXnkl5H7vvfee4XA4jD/96U8dHnPlypXGQw89ZGzevNl47733jIqKCuOwww4zysrKEv58Mkl3r937779vlJeXG//4xz+MHTt2GCtWrDBGjBhhTJo0KXifwJZ9Z599trFp0yZj9erVxsCBA9myL866e+2am5uNsWPHGoWFhcb7778fsm1Ra2urYRi87hLlmWeeMXJycozHHnvMeOedd4yrrrrK6N+/f3CHi9LSUuOWW24Jtq+rqzOys7ONu+66y9iyZYtx2223Rdyyr3///saKFSuMN99805g2bRpbhyVAd6/dr3/9a8PlchnLli0LeY0FtqP9/PPPjRtvvNFYv369sWPHDqO6uto45ZRTjOOOO8744osvUvIc7aq71+722283/vznPxvbtm0zNm7caFx00UVG3759jbfffjvYhtddcnT32gVMmDDBKCkp6XCc113yfP7558brr79uvP7664YkY+HChcbrr79u/POf/zQMwzBuueUWo7S0NNg+sGXfj3/8Y2PLli3GAw88EHHLvmi/DwhF6EfCfPbZZ8bFF19s9OvXz3C73cbll18efINjGIaxY8cOQ5Lx0ksvhdxv/vz5hsfjMdra2jo85p/+9Cdj9OjRRr9+/YzDDz/cOPnkk40lS5ZEbIue6+6127lzpzFp0iTjqKOOMnJycoxjjz3W+PGPf2w0NzeHPO4HH3xgnHPOOUZubq4xYMAA44YbbgjZFg69191r99JLLxmSIt527NhhGAavu0S67777jK997WuGy+UyzjjjDOPvf/978NyZZ55pXHrppSHtn332WaOgoMBwuVzG17/+deMPf/hDyPn29nbj1ltvNQYPHmzk5OQYZ511lrF169ZkPJWM051rd/TRR0d8jd12222GYRjG/v37jbPPPtsYOHCg0adPH+Poo482rrzySt68Jkh3rt31118fbDt48GDj3HPPNV577bWQx+N1lzzd/X/mu+++a0gy/vKXv3R4LF53ydPZe43A9br00kuNM888s8N9Ro8ebbhcLmPEiBHGo48+2uFxo/0+IJTDMNhzCQAAAAAAO2JNPwAAAAAANkXoBwAAAADApgj9AAAAAADYFKEfAAAAAACbIvQDAAAAAGBThH4AAAAAAGyK0A8AAAAAgE0R+gEAAAAAsClCPwAANudwOKLefv7zn/fqsV944YWQY7t27dL3vvc9FRQUyOl06vrrr4/psZYvX65vfOMbysvL0xFHHKGvf/3rMd8XAABElp3qDgAAgMTatWtX8L+rqqpUVlamrVu3Bo/169cvrv/egQMHNHDgQP3sZz/TokWLYrrPmjVrVFJSol/+8pc6//zz5XA49M477+jFF1+Ma98O1dbWJofDIaeTMRAAgH3xVw4AAJvLz88P3vLy8uRwOEKOPfPMMxo1apT69u2rkSNHqqKiInhfv9+va665RkOGDFHfvn119NFHa8GCBZKkYcOGSZKmT58uh8MR/H7YsGH6n//5H82YMUN5eXkx9XHVqlUqKirSj3/8Yx1//PEqKCjQBRdcoAceeKBDu9NPP119+/bVgAEDNH369OC5f//735oxY4aOPPJIHXbYYTrnnHP03nvvBc8/9thj6t+/v1auXKkTTjhBOTk52rlzpw4cOKAbb7xRX/nKV3T44Ydr7Nixqqmp6cFPGgCA9EPoBwAggz355JMqKyvTL3/5S23ZskW/+tWvdOutt+rxxx+XJN17771auXKlnn32WW3dulVPPvlkMNy/+uqrkqRHH31Uu3btCn7fE/n5+Xr77bf11ltvddrmD3/4g6ZPn65zzz1Xr7/+utasWaMzzjgjeP6yyy7TP/7xD61cuVLr16+XYRg699xz9eWXXwbb7N+/X3feeacefvhhvf322xo0aJCuueYarV+/Xs8884zefPNNfec739HUqVNDPjAAAMCqmN4PAEAGu+2223T33XeruLhYkjR8+HC98847evDBB3XppZdq586dOu644zRhwgQ5HA4dffTRwfsOHDhQktS/f3/l5+f3qh/XXnut1q5dq8LCQh199NH6xje+obPPPluXXHKJcnJyJEm//OUvddFFF+n2228P3u/kk0+WJL333ntauXKl6urqNH78eEnmBxoej0cvvPCCvvOd70iSvvzyS1VUVATvt3PnTj366KPauXOnhg4dKkm68cYbtXr1aj366KP61a9+1avnBQBAqjHSDwBAhtq3b5+2bdummTNnql+/fsHbL37xC23btk2SOXq+adMmHX/88bruuuv0l7/8JSF9Ofzww/WHP/z/9u4lFP41juP4x72Ru4Vbbk1mUCY/1ySRSzHUWMgoNaXYWpgFxYKtYmEnaqyUWKkzCrOwdCtlISUsZXJZDCWmOQudqX/nOItzyDnj/do9v57f83ue7+7T8/x+v990cXGhqakpJSUlye12q66uTs/Pz5Kkk5MTtbW1/eX9Z2dnio2NVX19ffhaZmamrFarzs7Owtfi4+Nls9nC7dPTUwWDQVksll9qsLe3F64BAAD/Z+z0AwDwQwUCAUnS0tLSL2FZkmJiYiRJVVVVurq60tbWlnZ3d9Xf36/29nZtbGx8yZzMZrPMZrOGh4c1OTkpi8WitbU1DQ0NyWQy/evxTSaToqKiwu1AIKCYmBgdHx+H1/yHz/7AIQAA34HQDwDAD5WVlaXc3FxdXl5qcHDww34pKSlyOp1yOp3q6+tTZ2en7u/vlZGRobi4OAWDwS+ZX1FRkRITE/X09CRJstls8vl8Ghoa+lPfsrIyvb29aX9/P3y8/+7uTufn5yovL//wGYZhKBgM6vb2Vk1NTV+yDgAAvhOhHwCAH2xmZkajo6NKTU1VZ2enXl5edHR0pIeHB42NjWl+fl45OTkyDEPR0dFaX19Xdna20tLSJL0Hc5/Pp8bGRiUkJCg9PV3S+1F86X0n3e/36+TkRPHx8R8G8OnpaT0/P8tut6uwsFCPj49aWFjQ6+urOjo6JL1/f6CtrU1ms1kDAwN6e3uT1+vV+Pi4SkpK5HA4NDIyosXFRSUnJ2tiYkJ5eXlyOBwfrt9isWhwcFAul0tzc3MyDEN+v18+n082m03d3d2fV2wAAL4B7/QDAPCDDQ8Pa3l5WR6PRxUVFWpubtbKyoqKi4slScnJyZqdnVVNTY1qa2t1fX0tr9cb/rf93NycdnZ2lJ+fL8MwwuMahiHDMHR8fKzV1VUZhiG73f7hPJqbm3V5eSmXy6XS0lJ1dXXp5uZG29vbslqtkqSWlhatr69rc3NTlZWVam1t1cHBQXgMj8ej6upq9fT0qKGhQaFQSF6vV3FxcX9bA4/HI5fLJbfbLavVqt7eXh0eHqqgoOAf1xUAgP+KqFAoFPruSQAAAAAAgM/HTj8AAAAAABGK0A8AAAAAQIQi9AMAAAAAEKEI/QAAAAAARChCPwAAAAAAEYrQDwAAAABAhCL0AwAAAAAQoQj9AAAAAABEKEI/AAAAAAARitAPAAAAAECEIvQDAAAAABChCP0AAAAAAESo3wFHBUNbjdJXUgAAAABJRU5ErkJggg==\n"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "positive = data[data['Accepted'].isin([1])]\n",
    "negative = data[data['Accepted'].isin([0])]\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(12, 8))\n",
    "ax.scatter(positive['Test1'], positive['Test2'], s=50, c='b', marker='o', label='Accepted')\n",
    "ax.scatter(negative['Test1'], negative['Test2'], s=50, c='r', marker='x', label='Rejected')\n",
    "ax.legend()\n",
    "ax.set_xlabel('Test1 Score')\n",
    "ax.set_ylabel('Test2 Score')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## 特征映射\n",
    "\n",
    "![](img/feature_map.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "   Accepted  Ones       F10       F20       F21       F30       F31       F32  \\\n0         1     1  0.051267  0.002628  0.035864  0.000135  0.001839  0.025089   \n1         1     1 -0.092742  0.008601 -0.063523 -0.000798  0.005891 -0.043509   \n2         1     1 -0.213710  0.045672 -0.147941 -0.009761  0.031616 -0.102412   \n3         1     1 -0.375000  0.140625 -0.188321 -0.052734  0.070620 -0.094573   \n4         1     1 -0.513250  0.263426 -0.238990 -0.135203  0.122661 -0.111283   \n\n        F40       F41       F42       F43  \n0  0.000007  0.000094  0.001286  0.017551  \n1  0.000074 -0.000546  0.004035 -0.029801  \n2  0.002086 -0.006757  0.021886 -0.070895  \n3  0.019775 -0.026483  0.035465 -0.047494  \n4  0.069393 -0.062956  0.057116 -0.051818  ",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>Accepted</th>\n      <th>Ones</th>\n      <th>F10</th>\n      <th>F20</th>\n      <th>F21</th>\n      <th>F30</th>\n      <th>F31</th>\n      <th>F32</th>\n      <th>F40</th>\n      <th>F41</th>\n      <th>F42</th>\n      <th>F43</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>1</td>\n      <td>1</td>\n      <td>0.051267</td>\n      <td>0.002628</td>\n      <td>0.035864</td>\n      <td>0.000135</td>\n      <td>0.001839</td>\n      <td>0.025089</td>\n      <td>0.000007</td>\n      <td>0.000094</td>\n      <td>0.001286</td>\n      <td>0.017551</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>1</td>\n      <td>1</td>\n      <td>-0.092742</td>\n      <td>0.008601</td>\n      <td>-0.063523</td>\n      <td>-0.000798</td>\n      <td>0.005891</td>\n      <td>-0.043509</td>\n      <td>0.000074</td>\n      <td>-0.000546</td>\n      <td>0.004035</td>\n      <td>-0.029801</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>1</td>\n      <td>1</td>\n      <td>-0.213710</td>\n      <td>0.045672</td>\n      <td>-0.147941</td>\n      <td>-0.009761</td>\n      <td>0.031616</td>\n      <td>-0.102412</td>\n      <td>0.002086</td>\n      <td>-0.006757</td>\n      <td>0.021886</td>\n      <td>-0.070895</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>1</td>\n      <td>1</td>\n      <td>-0.375000</td>\n      <td>0.140625</td>\n      <td>-0.188321</td>\n      <td>-0.052734</td>\n      <td>0.070620</td>\n      <td>-0.094573</td>\n      <td>0.019775</td>\n      <td>-0.026483</td>\n      <td>0.035465</td>\n      <td>-0.047494</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>1</td>\n      <td>1</td>\n      <td>-0.513250</td>\n      <td>0.263426</td>\n      <td>-0.238990</td>\n      <td>-0.135203</td>\n      <td>0.122661</td>\n      <td>-0.111283</td>\n      <td>0.069393</td>\n      <td>-0.062956</td>\n      <td>0.057116</td>\n      <td>-0.051818</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "degree = 5\n",
    "\n",
    "x1 = data['Test1']\n",
    "x2 = data['Test2']\n",
    "\n",
    "data.insert(3, 'Ones', 1)\n",
    "\n",
    "for i in range(1, degree):\n",
    "    for j in range(0, i):\n",
    "        data['F' + str(i) + str(j)] = np.power(x1, i-j) * np.power(x2, j)\n",
    "# 'Test1'表示要删除的列的名称。\n",
    "# axis=1表示删除的是列而不是行。axis=0表示删除行，axis=1表示删除列。\n",
    "# inplace=True表示在原始DataFrame上进行就地修改，即直接删除指定的列，而不返回一个新的DataFrame副本。\n",
    "\n",
    "data.drop('Test1', axis=1, inplace=True)\n",
    "data.drop('Test2', axis=1, inplace=True)\n",
    "\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## 正则化代价函数\n",
    "\n",
    "![](img/regularized_cost.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [],
   "source": [
    "# 接受一个数值或一个数组作为输入，并将每个元素转换为0到1之间的值。\n",
    "def sigmoid(z):\n",
    "    return 1 / (1 + np.exp(-z))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "outputs": [],
   "source": [
    "def costReg(theta, X, y, learningRate):\n",
    "    theta = np.matrix(theta)\n",
    "    X = np.matrix(X)\n",
    "    y = np.matrix(y)\n",
    "    first = np.multiply(-y, np.log(sigmoid(X * theta.T)))\n",
    "    second = np.multiply((1 - y), np.log(1 - sigmoid(X * theta.T)))\n",
    "    reg = (learningRate / (2 * len(X))) * np.sum(np.power(theta[:,1:theta.shape[1]], 2))\n",
    "    return np.sum(first - second) / len(X) + reg"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## 正则化梯度\n",
    "\n",
    "![](img/regularized_gradient.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "outputs": [],
   "source": [
    "# 计算步长\n",
    "def gradientReg(theta, X, y, learningRate):\n",
    "    theta = np.matrix(theta)\n",
    "    X = np.matrix(X)\n",
    "    y = np.matrix(y)\n",
    "    # theta.ravel()将矩阵theta展平为一个一维数组,shape[1]获取数组的第二个维度的大小，即参数的数量,\n",
    "    parameters = int(theta.ravel().shape[1])\n",
    "    grad = np.zeros(parameters)\n",
    "    error = sigmoid(X * theta.T) - y\n",
    "    for i in range(parameters):\n",
    "        term = np.multiply(error, X[:,i])\n",
    "        if (i == 0):\n",
    "            grad[i] = np.sum(term) / len(X)\n",
    "        else:\n",
    "            grad[i] = (np.sum(term) / len(X)) + ((learningRate / len(X)) * theta[:,i])\n",
    "\n",
    "    return grad"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## 拟合参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "outputs": [],
   "source": [
    "cols = data.shape[1]\n",
    "X2 = data.iloc[:,1:cols]\n",
    "y2 = data.iloc[:,0:1]\n",
    "\n",
    "X2 = np.array(X2.values)\n",
    "y2 = np.array(y2.values)\n",
    "theta2 = np.zeros(11)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "outputs": [],
   "source": [
    "learningRate = 1"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "outputs": [
    {
     "data": {
      "text/plain": "0.6931471805599454"
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "costReg(theta2, X2, y2, learningRate)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "outputs": [
    {
     "data": {
      "text/plain": "array([0.00847458, 0.01878809, 0.05034464, 0.01150133, 0.01835599,\n       0.00732393, 0.00819244, 0.03934862, 0.00223924, 0.01286005,\n       0.00309594])"
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gradientReg(theta2, X2, y2, learningRate)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "outputs": [
    {
     "data": {
      "text/plain": "(array([ 0.53010249,  0.29075567, -1.60725763, -0.5821382 ,  0.01781027,\n        -0.21329508, -0.40024142, -1.37144139,  0.02264303, -0.9503358 ,\n         0.0344085 ]),\n 22,\n 1)"
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import scipy.optimize as opt\n",
    "result = opt.fmin_tnc(func=costReg, x0=theta2, fprime=gradientReg, args=(X2, y2, learningRate))\n",
    "result"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## 预测分析"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "outputs": [],
   "source": [
    "def predict(theta, X):\n",
    "    probability = sigmoid(X @ theta.T)\n",
    "    # 列表推导式\n",
    "    return [1 if x >= 0.5 else 0 for x in probability]"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "accuracy = 66.10169491525424%\n"
     ]
    }
   ],
   "source": [
    "theta_min = np.matrix(result[0])\n",
    "predictions = predict(theta_min, X2)\n",
    "correct = [1 if ((a == 1 and b == 1) or (a == 0 and b == 0)) else 0 for (a, b) in zip(predictions, y2)]\n",
    "accuracy = (sum(map(int, correct)) / len(correct))\n",
    "print ('accuracy = {0}%'.format(accuracy*100))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "虽然我们实现了这些算法，值得注意的是，我们还可以使用高级Python库像scikit-learn来解决这个问题。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "outputs": [
    {
     "data": {
      "text/plain": "LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,\n                   intercept_scaling=1, l1_ratio=None, max_iter=100,\n                   multi_class='auto', n_jobs=None, penalty='l2',\n                   random_state=None, solver='lbfgs', tol=0.0001, verbose=0,\n                   warm_start=False)"
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn import linear_model#调用sklearn的线性回归包\n",
    "model = linear_model.LogisticRegression(penalty='l2', C=1.0)\n",
    "model.fit(X2, y2.ravel())"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "outputs": [
    {
     "data": {
      "text/plain": "0.6610169491525424"
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.score(X2, y2)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}